package net.youdi.gateway.handler.response;

import com.fasterxml.jackson.core.json.JsonReadFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.youdi.gateway.context.SensitiveContext;
import net.youdi.gateway.handler.SensitiveCacheHandler;
import net.youdi.gateway.properties.GatewayProperties;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import java.net.URLDecoder;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author: scl
 * @date: 2020-07-23 14:00
 * @description
 */
@Component
@Order(Integer.MIN_VALUE)
public class SensitiveResponseHandler implements ResponseDataHandler {
    private static String CHAR_SET = "UTF-8";
    private static String sensitiveFlag = "@sensitive\\((.*?)\\)";
    private static Pattern pattern = Pattern.compile(sensitiveFlag);
    private final GatewayProperties gatewayProperties;

    private final ObjectMapper objectMapper;

    public SensitiveResponseHandler(GatewayProperties gatewayProperties, ObjectMapper objectMapper) {
        this.gatewayProperties = gatewayProperties;
        this.objectMapper = objectMapper;
        this.objectMapper.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(),true);
    }

    @Override
    public Object handler(ServerWebExchange exchange, String data, Map container) {
        if (gatewayProperties.isNoSensitive(exchange.getRequest().getURI().getRawPath())){
           return data;
        }
        return rewrite(data,container);
    }

    private Object rewrite(String data, Map container) {
        String rs;
        Set<String> sensitives = new HashSet<>();
        try {
            rs = data.replaceAll("\\\\","");
            data = URLDecoder.decode(data,CHAR_SET);
        } catch (Exception e) {
            return data;
        }
        Matcher matcher = pattern.matcher(rs);
        while (matcher.find()){
            try {
                String all = matcher.group(0);
                String value = matcher.group(1);
                String[] split = value.split(",");
                value = URLDecoder.decode(split[0],CHAR_SET);
                if (Boolean.valueOf(split[1]) && SensitiveContext.hasSensitiveWord()){
                    value = SensitiveContext.replaceSensitiveWord(value, SensitiveContext.minMatchTYpe);
                }
                sensitives.add(value);
                data = data.replace(URLDecoder.decode(all,CHAR_SET),value);
            } catch (Exception e) {
            }
        }
        if (sensitives != null && !sensitives.isEmpty()){
            container.put(SensitiveCacheHandler.SENSITIVE_KEY,sensitives);
        }
        return data;
    }
}
